package io.plus.user_interface.io.common.protocol;

import io.plus.interactive.AsynchronousSocketChannelContext;
import io.plus.interactive.Configuration;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

@Slf4j
public class Encoder {

    public static ByteBuffer encode(PacketImpl tcpPacket, Configuration configuration, AsynchronousSocketChannelContext asynchronousSocketChannelContext) {

        //协议版本号
        byte version = ProtocolConstants.VERSION;
        tcpPacket.setVersion(version);
        //协议标志位mask
        boolean isEncrypt = true;
        boolean isCompress = true;
        boolean isHasSynSeq = tcpPacket.getSynSeq() > 0;
        boolean is4ByteLength = true;

        byte maskByte = ProtocolConstants.init_byte;
        maskByte = PacketImpl.encodeEncrypt(maskByte, isEncrypt);
        maskByte = PacketImpl.encodeCompress(maskByte, isCompress);
        maskByte = PacketImpl.encodeHasSynSeq(maskByte, isHasSynSeq);
        maskByte = PacketImpl.encode4ByteLength(maskByte, is4ByteLength);
        tcpPacket.setMask(maskByte);
        //
        byte commandByte = ProtocolConstants.init_byte;
        if (tcpPacket.getCommand() != null) {
            commandByte = (byte) (commandByte | tcpPacket.getCommand().getNumber());
        }
        int bodyLength = 0;
        byte[] body = tcpPacket.getBody();
        if (body != null) {
            bodyLength = body.length;
        }

        //byteBuffer的总长度是 = 1byte协议版本号+1byte消息标志位+4byte同步序列号(如果是同步发送则都4byte同步序列号,否则无4byte序列号)+1byte命令码+4byte消息的长度+消息体
        int allLength = 1 + 1;
        if (isHasSynSeq) {
            allLength += 4;
        }
        allLength += 1 + 4 + bodyLength;
        ByteBuffer byteBuffer = ByteBuffer.allocate(allLength);
        //设置字节序
        ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
        byteBuffer.order(byteOrder);
        byteBuffer.put(tcpPacket.getVersion());
        byteBuffer.put(tcpPacket.getMask());
        //同步发送设置4byte，同步序列号;
        if (isHasSynSeq) {
            byteBuffer.putInt(tcpPacket.getSynSeq());
        }
        byteBuffer.put(commandByte);
        byteBuffer.putInt(bodyLength);
        byteBuffer.put(body);
        return byteBuffer;
    }
}
